/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_orm.htm
 *
 * Zhiqim ORM is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.orm.impl;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;

import org.zhiqim.kernel.service.MultiInstancer;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.LinkedMapSO;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.model.maps.MapSS;
import org.zhiqim.kernel.paging.PageBuilder;
import org.zhiqim.kernel.paging.PageResult;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.orm.ORMConstants;
import org.zhiqim.orm.ORMException;
import org.zhiqim.orm.ORMI18n;
import org.zhiqim.orm.ORMServer;
import org.zhiqim.orm.ORMType;
import org.zhiqim.orm.ZSQL;
import org.zhiqim.orm.ZTable;
import org.zhiqim.orm.ZTab;
import org.zhiqim.orm.ZView;
import org.zhiqim.orm.annotation.AnTable;
import org.zhiqim.orm.annotation.AnTableField;
import org.zhiqim.orm.annotation.AnView;
import org.zhiqim.orm.annotation.AnViewField;
import org.zhiqim.orm.annotation.AnViewJoin;
import org.zhiqim.orm.annotation.AnViewJoinValue;
import org.zhiqim.orm.dbo.Selector;
import org.zhiqim.orm.dbo.defined._Table;
import org.zhiqim.orm.dbo.defined._TableField;
import org.zhiqim.orm.dbo.defined._View;
import org.zhiqim.orm.exception.TableNotExistException;

/**
 * 视图类与数据库表多表映射调用，支持(count,sum,item,list,page)<br><br>
 * count,       统计视图类对应的关联表数目<br>
 * sum,         总计视图类对应的关联表数目<br>
 * item,        查询视图类对应的关联表一条数据，根据主键，或根据条件排序取第一条<br>
 * list,        查询视图类对应的关联表列表，或根据条件排序<br>
 * pag,         分页查询视图类对应的关联表列表，指定分页页码和页数目<br>
 * 
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 * @version v1.2.0 @author zouzhigang 2016-6-27 修改原类名FRHELExcutor为ZViewExecutor，正式使用视图名称
 */
public final class ZViewImplement extends MultiInstancer implements ZView, ORMConstants
{
    private final ORMServer server;
    private final ZSQL zSQL;
    private final ZTab zTabler;
    private final ZTable zTable;
    private final HashSet<String> viewExistList;
    private final HashMap<Class<?>, _View> viewMap;
    
    public ZViewImplement(ORMServer server)
    {
        this.server = server;
        this.zSQL = server.sql();
        this.zTabler = server.tab();
        this.zTable = server.table();
        this.viewExistList = new HashSet<String>();
        this.viewMap = new HashMap<>();
    }
    
    /**
     * 通过视图类获取视图对象
     * 
     * @param cls       视图类
     * @return          视图对象
     */
    public _View getView(Class<?> cls)
    {
        _View _view = viewMap.get(cls);
        if (_view != null)
            return _view;
        
        AnView anView = cls.getAnnotation(AnView.class);
        if (anView == null)
            return null;
        
        String table = anView.value();
        _view = new _View(cls.getName(), table);
        
        //1.增加连接
        AnViewJoin join = cls.getAnnotation(AnViewJoin.class);
        if (join != null)
        {
            AnViewJoinValue[] values = join.value();
            for (AnViewJoinValue value : values)
            {
                _view.addJoin(value.type(), value.lTable(), value.lColumn(), value.rTable(), value.rColumn(), value.rValue());
            }
        }
        //2.增加字段
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields)
        {
            if (Classes.isStaticTransientField(field))
                continue;
            
            String fieldName = field.getName();
            
            AnViewField vfield = field.getAnnotation(AnViewField.class);
            if (vfield != null)
            {//从表中找字段
                _Table _table = zTable.getTableByTableName(_view.getTableName(vfield.table()));
                Asserts.assertNotNull(_table, ORMI18n.ormViewNotFountTable2, cls.getName(), vfield.table());
                
                _TableField _field = _table.getField(vfield.column());
                Asserts.assertNotNull(_field, ORMI18n.ormViewNotFoundField2, cls.getName(), fieldName);
                
                _view.addField(fieldName, vfield.table(), vfield.column(), _field.getType());
            }
        }
        
        //3.增加表字段
        Class<?> superClass = cls.getSuperclass();
        if (superClass != Object.class)
        {
            fields = superClass.getDeclaredFields();
            for (Field field : fields)
            {
                if (Classes.isStaticTransientField(field))
                    continue;
                
                String fieldName = field.getName();
                
                AnTableField tfield = field.getAnnotation(AnTableField.class);
                if (tfield != null)
                {
                    Class<?> fpclass = field.getDeclaringClass();
                    AnTable t = fpclass.getAnnotation(AnTable.class);
                    if (t != null)
                    {
                        int type = ORMType.getColumnTypeMaybeLength(tfield.type());
                        _view.addField(fieldName, t.table(), tfield.column(), type);
                    }
                }
            }
        }
        
        viewMap.put(cls, _view);
        return _view;
    }
    
    /*****************************************************/
    //count 查询数目
    /*****************************************************/
    
    /**
     * 查询数目，查全视图
     * 
     * @param cls           视图类
     * @return              返回数目
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int count(Class<?> cls)throws ORMException, SQLException
    {
        return count(cls, new Selector());
    }
    
    /**
     * 查询数目，根据条件、可替换表查询
     * 
     * @param cls           视图类
     * @param selector      对象查询器
     * @return              返回数目
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public int count(Class<?> cls, Selector selector)throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[count][selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[count]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        MapSO paramMap = new HashMapSO();
        StringBuilder sql = new StringBuilder("select count(*) from ");
        sql.append(_view.getJoinTable(zTable, selector, paramMap));         //连接表
        sql.append(selector.getWhereSQL(_view, paramMap));                  //自定义条件
        
        try
        {//执行SQL
            List<Integer> list = zSQL.executeQuery(sql.toString(), Integer.class, paramMap, selector.getReplaceMap());
            return list.get(0);
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            List<Integer> list = zSQL.executeQuery(sql.toString(), Integer.class, paramMap, selector.getReplaceMap());
            return list.get(0);
        }
    }
    
    /**
     * 分组查询数目，根据条件、可替换表和分组字段
     * 
     * @param cls           表类
     * @param selector
     * @return
     * @throws ORMException
     * @throws SQLException
     */
    public List<MapSO> countGroupBy(Class<?> cls, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[count][selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[count]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        //组装SQL
        MapSO paramMap = new HashMapSO();
        String groupbyFieldsSQL = selector.getGroupbyFieldsSQL(_view);
        StringBuilder sql = new StringBuilder("select ").append(groupbyFieldsSQL).append(", count(*) as _COUNT_ from ");
        sql.append(_view.getJoinTable(zTable, selector, paramMap));         //连接表
        sql.append(selector.getWhereSQL(_view, paramMap));                  //自定义条件
        sql.append(selector.getGroupbySQL(_view));
        
        try
        {//执行SQL
            return zSQL.executeQuery(sql.toString(), MapSO.class, paramMap, selector.getReplaceMap());
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            return zSQL.executeQuery(sql.toString(), MapSO.class, paramMap, selector.getReplaceMap());
        }
    }
    
    /*****************************************************/
    //sum 计算总和
    /*****************************************************/
    
    /**
     * 计算总和，全视图求和
     * 
     * @param cls         视图类
     * @param field         视图字段
     * @return              返回总和
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public long sum(Class<?> cls, String field) throws ORMException, SQLException
    {
        return sum(cls, field, new Selector());
    }

    /**
     * 计算总和，根据条件视图中求和
     * 
     * @param cls           视图类
     * @param field         视图字段
     * @param selector      查询器
     * @return              返回总和(sum)
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public long sum(Class<?> cls, String field, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[sum][Selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[sum]["+cls.getName()+"]未找到相应的配置]");
        
        String column = _view.getColumn(field);
        if (column == null)
            throw new ORMException("ZView[sum]["+cls.getName()+"]配置中未找到["+field+"]字段");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        MapSO paramMap = new HashMapSO();
        StringBuilder sql = new StringBuilder("select sum(").append(column).append(")");
        sql.append(" from ").append(_view.getJoinTable(zTable, selector, paramMap));         //连接表
        sql.append(selector.getWhereSQL(_view, paramMap));                                   //自定义条件
        
        try
        {//执行SQL
            List<Long> list = zSQL.executeQuery(sql.toString(), Long.class, paramMap, selector.getReplaceMap());
            return list.isEmpty()?0:list.get(0);
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            List<Long> list = zSQL.executeQuery(sql.toString(), Long.class, paramMap, selector.getReplaceMap());
            return list.isEmpty()?0:list.get(0);
        }
    }
    
    /**
     * 计算多个总和，全视图中多个求和
     * 
     * @param cls           视图类
     * @param fieldArr      多个视图字段
     * @return              返回计算多个总和
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public long[] sum(Class<?> cls, String[] fieldArr) throws ORMException, SQLException
    {
        return sum(cls, fieldArr, new Selector());
    }
    
    /**
     * 计算多个总和，根据条件视图中多个求和
     * 
     * @param cls           视图类
     * @param fieldArr      多个视图字段
     * @param selector      查询器
     * @return              返回计算多个总和
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public long[] sum(Class<?> cls, String[] fieldArr, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[sum][selector]不允许为NULL]");
        
        if (fieldArr == null || fieldArr.length < 1)
            throw new ORMException("ZView[sum][fieldArr]不能为空]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[sum]["+cls.getName()+"]未找到相应的配置]");
        
        if (!_view.hasAllField(fieldArr))
            throw new ORMException("ZView[sum]["+Arrays.toString(fieldArr)+"]有未找到的字段");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        StringBuilder sql = new StringBuilder("select ");
        //第一个
        String column = _view.getColumn(fieldArr[0]);
        sql.append(" sum(").append(column).append(") as ").append(fieldArr[0]);
        //后面的
        for (int i=1;i<fieldArr.length;i++)
        {
            column = _view.getColumn(fieldArr[i]);
            sql.append(", sum(").append(column).append(") as ").append(fieldArr[i]);
        }
        
        HashMapSO paramMap = new HashMapSO();
        sql.append(" from ").append(_view.getJoinTable(zTable, selector, paramMap))
           .append(selector.getWhereSQL(_view, paramMap));
        
        List<LinkedMapSO> list = null;
        try
        {//执行SQL
            list = zSQL.executeQuery(sql.toString(), LinkedMapSO.class, paramMap, selector==null?null:selector.getReplaceMap());
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            list = zSQL.executeQuery(sql.toString(), LinkedMapSO.class, paramMap, selector==null?null:selector.getReplaceMap());
        }
        
        if (list.isEmpty())
            return new long[fieldArr.length];

        LinkedMapSO item = list.get(0);
        long[] valueArr = new long[fieldArr.length];
        for (int i=0;i<fieldArr.length;i++)
        {//默认为数值型，需要转化为long
            BigDecimal value = (BigDecimal)item.get(fieldArr[i]);
            if (value == null)
                valueArr[i] = 0;
            else
                valueArr[i] = value.longValue();
        }
        return valueArr;
    }
    
    /*****************************************************/
    //item 查询一条数据
    /*****************************************************/
    
    /**
     * 查询一个视图对象,全视图中取第一个
     * 
     * @param cls           视图类
     * @return              返回视图对象
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> T item(Class<T> cls) throws ORMException, SQLException
    {
        return item(cls, new Selector());
    }
    
    /**
     * 查询一个视图对象,可排序取第一个
     * 
     * @param cls           视图类
     * @param selector      查询器
     * @return              返回视图对象
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> T item(Class<T> cls, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[item][Selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[item]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        //组装SQL
        MapSO paramMap = new HashMapSO();
        String tableName = _view.getJoinTable(zTable, selector, paramMap);
        String fieldSQL = _view.getDefaultFieldSQL(selector.getFields());
        String whereSQL = selector.getWhereSQL(_view, paramMap);
        String orderbySQL = selector.getOrderbySQL(_view);
        String groupbySQL = selector.getGroupbySQL(_view);
        String sql = server.getPolicy().toItemSQL(fieldSQL, tableName, whereSQL, orderbySQL, groupbySQL);
        
        List<T> list = null;
        try
        {//执行SQL
            list = zSQL.executeQuery(sql.toString(), cls, paramMap, selector.getReplaceMap());
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            list = zSQL.executeQuery(sql.toString(), cls, paramMap, selector.getReplaceMap());
        }
        
        if (list.isEmpty())
            return null;
        
        T item = list.get(0);
        _view.addReplaceToData(zTable, item, selector.getReplaceMap());
        return item;
    }
    
    /*****************************************************/
    //list 查询列表
    /*****************************************************/
    
    /**
     * 查询列表，查全视图
     * 
     * @param cls           视图类
     * @return              视图对象列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls) throws ORMException, SQLException
    {
        return list(cls, new Selector());
    }
    
    /**
     * 查询列表，根据查询器
     * 
     * @param cls           视图类
     * @param selector      查询器
     * @return              视图对象列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[list][selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[list]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        //组装SQL
        MapSO paramMap = new HashMapSO();
        StringBuilder sql = new StringBuilder("select ").append(_view.getDefaultFieldSQL(selector.getFields()));    //字段
        sql.append(" from ").append(_view.getJoinTable(zTable, selector, paramMap));                                //连接表
        sql.append(selector.getWhereSQL(_view, paramMap));                                                          //自定义条件
        sql.append(selector.getOrderbySQL(_view));                                                                  //自定义排序
        sql.append(selector.getGroupbySQL(_view));                                                                  //自定义分组
        
        List<T> list = null;
        try
        {//执行SQL
            list = zSQL.executeQuery(sql.toString(), cls, paramMap, selector.getReplaceMap());
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            list = zSQL.executeQuery(sql.toString(), cls, paramMap, selector.getReplaceMap());
        }
        
        //检查有没有可替换参数
        for (T item : list)
        {
            _view.addReplaceToData(zTable, item, selector.getReplaceMap());
        }
        
        return list;
    }
    
    /**
     * 查询表对象列表，查询指定的位置的数据
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @return              返回表对象列表
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls, int pageNo, int pageSize) throws ORMException, SQLException
    {
        return list(cls, pageNo, pageSize, new Selector());
    }
    
    /**
     * 查询表对象列表，并指定位置的,条件和排序条件
     * 
     * @param cls           表类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param selector      对象查询器
     * @return              返回表对象列表
     * @throws ORMException 映射异常,如果传入的属性不在配置文件中则异常
     * @throws SQLException 数据库异常
     */
    public <T> List<T> list(Class<T> cls, int pageNo, int pageSize, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[list][selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[list]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        //检查页码最小值和页大小有效性
        pageNo = (pageNo < 1)?1:pageNo;
        pageSize = (pageSize < 1)?10:pageSize;
        
        //执行SQL
        return list(_view, cls, pageNo, pageSize, selector);
    }
    
    /*****************************************************/
    //page 分页显示
    /*****************************************************/
    
    /**
     * 查询视图分页信息，查全视图
     * 
     * @param cls           视图类
     * @param pageNo        页码
     * @param pageSize      页数
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize) throws ORMException, SQLException
    {
        return page(cls, pageNo, pageSize, new Selector());
    }
    
    /**
     * 查询视图分页信息
     * 
     * @param cls           视图类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param selector      查询器
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[page][selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[page]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        //检查页码最小值和页大小有效性
        pageNo = (pageNo < 1)?1:pageNo;
        pageSize = (pageSize < 1)?10:pageSize;
        
        //先查数目
        int total = count(cls, selector);
        if (total == 0)
            return PageBuilder.newResult(pageNo, pageSize);
        
        //检查页码最大值有效性
        int pageMax = (total-1) / pageSize + 1;
        pageNo = (pageNo > pageMax)?pageMax:pageNo;
        
        //执行SQL
        List<T> list = list(_view, cls, pageNo, pageSize, selector);
        return PageBuilder.newResult(total, pageNo, pageSize, list);
    }
    
    /**
     * 查询视图分页信息，查全视图
     * 
     * @param cls           视图类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param total         指定总数，不作count计算
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize, int total) throws ORMException, SQLException
    {
        return page(cls, pageNo, pageSize, total, new Selector());
    }
    
    /**
     * 查询视图分页信息
     * 
     * @param cls           视图类
     * @param pageNo        页码
     * @param pageSize      页数
     * @param selector      查询器
     * @param total         指定总数，不作count计算
     * @return              分页信息,包括总页数,页码,页数和查询的记录
     * @throws ORMException 映射异常
     * @throws SQLException 数据库异常
     */
    public <T> PageResult<T> page(Class<T> cls, int pageNo, int pageSize, int total, Selector selector) throws ORMException, SQLException
    {
        if (selector == null)
            throw new ORMException("ZView[page][selector]不允许为NULL]");
        
        _View _view = getView(cls);
        if (_view == null)
            throw new ORMException("ZView[page]["+cls.getName()+"]未找到相应的配置]");
        
        //检查表是否存在，当前仅支持MYSQL
        createJoinTable(_view, selector.getReplaceMap());
        
        //检查页码最小值和页大小有效性
        pageNo = (pageNo < 1)?1:pageNo;
        pageSize = (pageSize < 1)?10:pageSize;
        
        //检查页码最大值有效性
        int pageMax = (total-1) / pageSize + 1;
        pageNo = (pageNo > pageMax)?pageMax:pageNo;
        
        //执行SQL
        List<T> list = list(_view, cls, pageNo, pageSize, selector);
        return PageBuilder.newResult(total, pageNo, pageSize, list);
    }
    
    /** 内部方法，list & page 调用 */
    private <T> List<T> list(_View _view, Class<T> cls, int pageNo, int pageSize, Selector selector) throws ORMException, SQLException
    {
        int minNum = (pageNo-1) * pageSize + 1;
        int maxNum = pageNo * pageSize;
        MapSO paramMap = new HashMapSO();
        paramMap.put("minNum", new Integer(minNum));
        paramMap.put("maxNum", new Integer(maxNum));
        paramMap.put("minSize", new Integer(minNum - 1));
        paramMap.put("pageSize", new Integer(pageSize));
        
        //组装SQL
        String whereSQL = selector.getWhereSQL(_view, paramMap);
        String orderbySQL = selector.getOrderbySQL(_view);
        String groupbySQL = selector.getGroupbySQL(_view);
        
        StringBuilder innerTableSQL = new StringBuilder(" ( select ");
        innerTableSQL.append(_view.getDefaultFieldSQL(selector.getFields()));                   //字段
        innerTableSQL.append(" from ").append(_view.getJoinTable(zTable, selector, paramMap));  //连接表
        innerTableSQL.append(whereSQL);                                                         //自定义条件
        innerTableSQL.append(orderbySQL);                                                       //自定义排序
        innerTableSQL.append(groupbySQL);                                                       //自定义分组
        innerTableSQL.append(" ) ");

        String sql = server.getPolicy().toPageViewSQL(innerTableSQL, maxNum, pageNo);
        
        List<T> list = null;
        try
        {//执行SQL
            list = zSQL.executeQuery(sql, cls, paramMap, selector.getReplaceMap());
        }
        catch(TableNotExistException e)
        {//表不存在重作一次（可能被管理员删除，对误操作增加的保险机制）
            createJoinTable(_view, selector.getReplaceMap(), true);
            list = zSQL.executeQuery(sql, cls, paramMap, selector.getReplaceMap());
        }
        
        //检查有没有可替换参数
        for (T item : list)
        {
            _view.addReplaceToData(zTable, item, selector.getReplaceMap());
        }
        
        return list;
    }
    
    /** 检查创建表 */
    private void createJoinTable(_View _view, MapSS replaceMap) throws SQLException, ORMException
    {
        createJoinTable(_view, replaceMap, false);
    }
    
    /** 检查创建表 */
    private void createJoinTable(_View _view, MapSS replaceMap, boolean isException) throws SQLException, ORMException
    {
        //统一兼容表名可替换参数（即支持date参数方式和可替换参数DATE方式）
        _view.chkTableReplace(zTable, replaceMap);
        
        String viewName = _view.getName();
        if (replaceMap != null)
        {//如果替换表不为null则加进去
            StringBuilder strb = new StringBuilder(viewName);
            for (Entry<String, String> entry : replaceMap.entrySet())
            {
                strb.append("_").append(entry.getKey()).append("_").append(entry.getValue());
            }
            viewName = strb.toString();
        }
        
        //检查表是否存在，当前仅支持MYSQL
        if (!isException && viewExistList.contains(viewName))
            return;
        
        List<String> tableList = _view.getTableNoAliasList();
        for (String table : tableList)
        {
            _Table _table = zTable.getTableByTableName(table);
            if (_table == null)
                throw new ORMException("ZView[createJoinTable]["+_view.getName()+"]未找到相应["+table+"]的配置");
            
            zTabler.create(_table, replaceMap, isException);
        }
        
        viewExistList.add(viewName);
    }
}
